package service

import (
	"booksmart/book/internal/domain"
	"booksmart/book/internal/repository"
	logger2 "booksmart/book/pkg/logger"
	"context"
	"time"
)

type JobService interface {
	//抢占任务
	Preempt(ctx context.Context) (domain.Job, error)
	ResetNextTime(ctx context.Context, j domain.Job) error
}

type MysqlJobService struct {
	repo            repository.MysqlJobRepository
	l               logger2.LoggerV1
	refreshInterval time.Duration
}

func (m *MysqlJobService) ResetNextTime(ctx context.Context, j domain.Job) error {
	nextTime := j.NextTime()
	if nextTime.IsZero() {
		return m.repo.Stop(ctx, j.Id)
	}
	return m.repo.UpdateNextTime(ctx, nextTime, j.Id)
}

func (m *MysqlJobService) Preempt(ctx context.Context) (domain.Job, error) {
	job, err := m.repo.Preempt(ctx)
	if err != nil {
		return domain.Job{}, err
	}
	ticker := time.NewTicker(m.refreshInterval)
	//抢到了，续约
	go func() {
		for _ = range ticker.C {
			_ = m.Refresh(job.Id)

		}
	}()
	job.CancelFunc = func() error {
		ticker.Stop() //取消续约
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		err := m.repo.Release(ctx, job.Id)
		if err != nil {
			return err
		}
		return nil

	}
	return job, nil
}

func (m *MysqlJobService) Refresh(id int64) error {
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	err := m.repo.UpdateUtime(ctx, id)
	if err != nil {
		//续约失败，记录日志， 可以不用管
		m.l.Error("续约失败", logger2.Error(err))
	}
	return nil
}
